package com.zmn.oms.dubbo.impl.zmn.master.order;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderRemarkDetail;
import com.zmn.base.product.common.dto.categ.CategProductDRO;
import com.zmn.base.product.common.query.categ.CategProductQuery;
import com.zmn.base.product.dubbo.interfaces.categ.CategProductListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.math.MathUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import com.zmn.oms.business.interfaces.orderattachment.OrderAttachmentBService;
import com.zmn.oms.business.interfaces.orderamount.OrderDiscountCalcBService;
import com.zmn.oms.business.interfaces.work.OrderWorkListBService;
import com.zmn.oms.business.interfaces.work.OrderWorkProgrammeBService;
import com.zmn.oms.business.interfaces.work.masterwork.MasterWorkBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.constant.TriggerAmountChangeEnum;
import com.zmn.oms.common.dro.redistribute.WorkRedistributeListItemDRO;
import com.zmn.oms.common.enums.EncryptFieldTypeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.ProductInfoUtil;
import com.zmn.oms.dubbo.dto.common.work.*;
import com.zmn.oms.dubbo.dto.zmn.order.OrderDetailDRO;
import com.zmn.oms.dubbo.interfaces.zmn.master.order.MasterWorkListRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.oms.model.bo.orderamount.DiscountConditionParamsDIO;
import com.zmn.oms.model.bo.orderamount.OrderAmountDIO;
import com.zmn.oms.model.bo.orderamount.ReCalcOrderAmountDIO;
import com.zmn.oms.model.dto.warranty.MasterWorkWarrantyDTO;
import com.zmn.oms.model.dto.work.masterwork.*;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.discount.OrderDiscount;
import com.zmn.oms.model.entity.operation.OrderOperation;
import com.zmn.oms.model.entity.orderattachment.OrderAttachmentQuery;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkQuery;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWork;
import com.zmn.oms.model.vo.work.attachmen.OrderWorkAttachmentDetailVO;
import com.zmn.oms.model.vo.work.attachmen.OrderWorkAttachmentVO;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.discount.OrderDiscountService;
import com.zmn.oms.services.interfaces.operation.OrderOperationService;
import com.zmn.oms.services.interfaces.orderencrypt.OrderEncryptService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.business.interfaces.work.masterwork.ZsMasterWorkBService;
import com.zmn.pay.common.constant.PayConsts;
import com.zmn.saas.dubbo.constant.SaasDubboConsts;
import com.zmn.saas.dubbo.interfaces.quotation.QuotationModifyRemoteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;

/**
 * 类描述：师傅工单列表
 *
 * @author heciqi
 * @date 2020/03/27 13:46
 */
@Slf4j
@Service(loadbalance = "roundrobin", timeout = 10000, retries = 2, version = DubboConsts.INTERFACE_VERSION, validation = "false")
public class MasterWorkListRemoteServiceImpl implements MasterWorkListRemoteService {
	@Autowired
	private ZsMasterWorkBService zsMasterWorkBService;
	@Autowired
	private OrderWorkService orderWorkService;
	@Autowired
	private OrderAttachmentBService orderAttachmentBService;
	@Autowired
	private OrderDiscountCalcBService orderDiscountCalcBService;
	@Autowired
	private OrderDiscountService orderDiscountService;
	@Autowired
	private OrderWorkEsBService orderWorkEsBService;
	@Autowired
	private OrderWorkListBService orderWorkListBService;
	@Autowired
	private OrderDetailService orderDetailService;
	@Autowired
	private OrderOperationService orderOperationService;
	@Autowired
	private OrderWorkProgrammeBService orderWorkProgrammeBService;
	@Autowired
	private MasterWorkBService masterWorkBService;
	@Autowired
	private OrderEncryptService orderEncryptService;

	@Reference(version = SaasDubboConsts.INTERFACE_VERSION, check = false)
	private QuotationModifyRemoteService quotationModifyRemoteService;
	@Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
	private CategProductListRemoteService categProductListRemoteService;

	/**
	 * 工单详情
	 *
	 * @param masterWorkDIO
	 */
	@Override
	public ResponseDTO<WorkDetailDRO> getWorkDetail(MasterWorkDIO masterWorkDIO) {
		Long orderId = NumberUtil.isNotNullOrZero(masterWorkDIO.getOrderId()) ? masterWorkDIO.getOrderId() : masterWorkDIO.getWorkId();

		try {
			log.debug("工程师查询工单详情 orderId={},workId={},masterId={}", orderId, masterWorkDIO.getWorkId(), masterWorkDIO.getMasterId());
			WorkDetailDTO workDetailDTO = zsMasterWorkBService.getWorkDetail(masterWorkDIO.getPlat(),
					orderId, masterWorkDIO.getWorkId(), masterWorkDIO.getMasterId(),
					masterWorkDIO.getAgent());
			WorkDetailDRO workDetailDRO = BeanMapper.map(workDetailDTO, WorkDetailDRO.class);
			log.info("工程师查询工单详情 getWorkDetail orderId={} ,{}", orderId,JSON.toJSONString(workDetailDTO));

			return ResponseDTO.success(workDetailDRO);
		} catch (OmsBaseException e) {
			return ResponseDTO.fail(e.getCode(), e.getMessage());
		}
	}

	/**
	 * 工单简版详情
	 *
	 * @param masterWorkDIO
	 */
	@Override
	public ResponseDTO<WorkDetailDRO> getSimpleWorkDetail(MasterWorkDIO masterWorkDIO) {
		try {
			WorkDetailDTO workDetail = zsMasterWorkBService.getWorkSimpleDetail(masterWorkDIO.getPlat(),
					masterWorkDIO.getOrderId(), masterWorkDIO.getWorkId());
			WorkDetailDRO workDetailDRO = BeanMapper.map(workDetail, WorkDetailDRO.class);
			return ResponseDTO.success(workDetailDRO);
		} catch (OmsBaseException e) {
			return ResponseDTO.fail(e.getCode(), e.getMessage());
		}
	}

	/**
	 * 进行中工单列表
	 *
	 * @param masterWorkDIO
	 */
	@Override
	public ResponseDTO<WorkListDRO> getDoingWork(MasterWorkDIO masterWorkDIO) {
		try {
			WorkListDTO workListDTO = zsMasterWorkBService.getWorkingList(masterWorkDIO.getMasterId());
			if (log.isDebugEnabled()) {
				log.debug("#MasterWorkListRemoteService# getDoingWork 出参：[{}]",JSON.toJSONString(workListDTO));
			}
			WorkListDRO workListDRO = BeanMapper.map(workListDTO, WorkListDRO.class);
			if (log.isDebugEnabled()) {
				log.debug("#MasterWorkListRemoteService# getDoingWork 入参：[{}],出参：[{}]", JSON.toJSONString(masterWorkDIO), JSON.toJSONString(workListDRO));
			}
			return ResponseDTO.success(workListDRO);
		} catch (OmsBaseException e) {
			return ResponseDTO.fail(e.getCode(), e.getMessage());
		}
	}

	/**
	 * 获取改派工单
	 * @param masterWorkDIO
	 * @return
	 */
	@Override
	public ResponseDTO<List<WorkRedistributeListItemDRO>> listRedistributeWork(MasterWorkDIO masterWorkDIO) {
		try {
			List<WorkRedistributeListItemDTO> workListDTO = masterWorkBService.getRedistributingList(masterWorkDIO.getMasterId());

			return ResponseDTO.success(BeanMapper.mapList(workListDTO, WorkRedistributeListItemDRO.class));
		} catch (OmsBaseException e) {
			return ResponseDTO.fail(e.getCode(), e.getMessage());
		}
	}

	/**
	 * 搜索进行中工单
	 *
	 * @param orderListDIO 查询条件
	 */
	@Override
	public ResponseDTO<WorkListDRO> listDoingWorkByQuery(OrderListDIO orderListDIO) {
		try {
			WorkListDTO workListDTO = masterWorkBService.listDoingWorkByQuery(orderListDIO.getMasterId(), orderListDIO.getText());
			WorkListDRO workListDRO = BeanMapper.map(workListDTO, WorkListDRO.class);
			return ResponseDTO.success(workListDRO);
		} catch (OmsBaseException e) {
			return ResponseDTO.fail(e.getCode(), e.getMessage());
		}
	}

	/**
	 * 已完成工单列表
	 *
	 * @param masterWorkDIO
	 * @return
	 */
	@Override
	public ResponseDTO<WorkListDRO> getCompletedWork(MasterWorkDIO masterWorkDIO) {
		// 已完成工单限定在两个月内，上月和当月
		// 上个月1号到当前时间
		Date endDate = DateUtil.getNow();
		Date startDate = DateUtil.parse(DateUtil.getMonthFirstDay(DateUtil.addMonth(endDate, -1)), DateUtil.FORMAT_DEFAULT);

		try {
			WorkListDTO workListDTO = zsMasterWorkBService.getCompleteWorkList(masterWorkDIO.getPlat(),
					masterWorkDIO.getMasterId(), startDate, endDate, masterWorkDIO.getStartIndex(), masterWorkDIO.getPageSize());
			WorkListDRO workListDRO = BeanMapper.map(workListDTO, WorkListDRO.class);
			return ResponseDTO.success(workListDRO);
		} catch (OmsBaseException e) {
			return ResponseDTO.fail(e.getCode(), e.getMessage());
		}
	}

	/**
	 * 已完成工单列表（新接口）
	 *
	 * @param masterWorkDIO
	 * @return
	 */
	@Override
	public ResponseDTO<List<WorkListItemDRO>> listCompletedWork(MasterWorkDIO masterWorkDIO) {
		if (log.isDebugEnabled()) {
			log.debug("listCompletedWork==>{}", JSON.toJSONString(masterWorkDIO));
		}
		if (NumberUtil.isNullOrZero(masterWorkDIO.getYearMonth())) {
			return ResponseDTO.fail("时间参数有误");
		}

		Date startDate;
		Date endDate;
		try {
			Integer year = Integer.valueOf(String.valueOf(masterWorkDIO.getYearMonth()).substring(0, 4));
			Integer month = Integer.valueOf(String.valueOf(masterWorkDIO.getYearMonth()).substring(4, 6));
			startDate = DateUtil.getMonthStart(year, month);
			endDate = DateUtil.getMonthEnd(year, month);
		} catch (Exception e) {
			return ResponseDTO.fail("时间格式有误");
		}

		try {
			List<WorkListItemDTO> workListItemDTOS = masterWorkBService.listCompleteWorkFromEs(masterWorkDIO.getPlat(),
					masterWorkDIO.getMasterId(), masterWorkDIO.getTabType(), startDate, endDate, masterWorkDIO.getStartIndex(), masterWorkDIO.getPageSize());
			List<WorkListItemDRO> workListDROS = BeanMapper.mapList(workListItemDTOS, WorkListItemDRO.class);
			if (log.isDebugEnabled()) {
				log.debug("listCompletedWork出参===>{}", workListDROS);
			}
			return ResponseDTO.success(workListDROS);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return ResponseDTO.fail("获取历史工单异常");
		}
	}

	/**
	 * 历史工单详情
	 *
	 * @param masterWorkDIO
	 */
	@Override
	public ResponseDTO<WorkDetailDRO> getHisWorkDetail(MasterWorkDIO masterWorkDIO) {
		try {
			WorkDetailDTO workDetail = zsMasterWorkBService.getHisWorkDetail(masterWorkDIO.getPlat(),
					masterWorkDIO.getOrderId(), masterWorkDIO.getWorkId(), masterWorkDIO.getMasterId(),
					masterWorkDIO.getAgent());
			WorkDetailDRO workDetailDRO = BeanMapper.map(workDetail, WorkDetailDRO.class);
			return ResponseDTO.success(workDetailDRO);
		} catch (OmsBaseException e) {
			return ResponseDTO.fail(e.getCode(), e.getMessage());
		}
	}

	/**
	 * 获取工单可派单工程师列表
	 *
	 * @param masterWorkDIO
	 */
	@Override
	public ResponseDTO<WorkDistributeMasterDRO> getWorkDistributeMasterList(MasterWorkDIO masterWorkDIO) {
		try {
			WorkDistributeMasterDTO workDistributeMasterDTO = zsMasterWorkBService.getWorkDistributeMasterList(
					masterWorkDIO.getOrderId(), masterWorkDIO.getWorkId());
			WorkDistributeMasterDRO workDistributeMasterDRO = BeanMapper.map(workDistributeMasterDTO,
					WorkDistributeMasterDRO.class);
			return ResponseDTO.success(workDistributeMasterDRO);
		} catch (OmsBaseException e) {
			return ResponseDTO.fail(e.getCode(), e.getMessage());
		}
	}

	/**
	 * 用户报价显示相关信息
	 *
	 * @param quotationShowDIO
	 */
	@Override
	public ResponseDTO<WorkQuotationShowDRO> getQuotationShow(BaseRequestDIO quotationShowDIO) {
		OrderWork orderWork = orderWorkService.findOrderWorkByKey(quotationShowDIO.getOrderId(), quotationShowDIO.getWorkId());
		WorkQuotationShowDTO workQuotationShowDTO = zsMasterWorkBService.getQuotationShow(orderWork);
		WorkQuotationShowDRO workQuotationShowDRO = BeanMapper.map(workQuotationShowDTO, WorkQuotationShowDRO.class);
		workQuotationShowDRO.setServItemType(orderWork != null ? orderWork.getServItemType() : OrderConsts.SERVICE_ITEM_TYPE_ORDER);
		return ResponseDTO.success(workQuotationShowDRO);
	}

	@Override
	public ResponseDTO<MasterWorkOperateCheckInfoDRO> getMasterWorkOperateCheckInfo(BaseRequestDIO baseRequestDIO) {
		try {
			MasterWorkOperateCheckInfoDTO masterWorkOperateCheckInfo = zsMasterWorkBService.getMasterWorkOperateCheckInfo(baseRequestDIO.getOrderId(), baseRequestDIO.getWorkId());

			MasterWorkOperateCheckInfoDRO workOperateCheckInfoDRO = MasterWorkOperateCheckInfoDRO.builder()
					.isWallWaterproofQuotation(masterWorkOperateCheckInfo.getIsWallWaterproofQuotation())
					.isWallQuotation(masterWorkOperateCheckInfo.getIsWallQuotation())
					.bizType(masterWorkOperateCheckInfo.getBizType())
					.servItemType(masterWorkOperateCheckInfo.getServItemType())
					.status(masterWorkOperateCheckInfo.getStatus())
					.resultStatus(masterWorkOperateCheckInfo.getResultStatus())
					.hasProduct(masterWorkOperateCheckInfo.getHasProduct())
					.hasConfirmQuotation(masterWorkOperateCheckInfo.getHasConfirmQuotation())
					.hasDifficultRetio(masterWorkOperateCheckInfo.getHasDifficultRetio())
					.needUploadMasterPicture(masterWorkOperateCheckInfo.getNeedUploadMasterPicture())
					.hasQuotationQRCode(masterWorkOperateCheckInfo.getHasQuotationQRCode())
					.hasOperateVisitScan(masterWorkOperateCheckInfo.getHasOperateVisitScan())
					.channelId(masterWorkOperateCheckInfo.getChannelId())
					.showProductId(masterWorkOperateCheckInfo.getShowProductId())
					.isSubmitCheckReport(masterWorkOperateCheckInfo.getIsSubmitCheckReport())
					.isUserScan(masterWorkOperateCheckInfo.getIsUserScan())
					.hasCheckProductByEngineer(masterWorkOperateCheckInfo.getHasCheckProductByEngineer())
					.hasAgreeResult(masterWorkOperateCheckInfo.getHasAgreeResult())
					.isConfirmFault(masterWorkOperateCheckInfo.getIsConfirmFault())
					.isStartCheck(masterWorkOperateCheckInfo.getIsStartCheck())
					.needUploadEquipmentPicture(masterWorkOperateCheckInfo.getNeedUploadEquipmentPicture())
					.needUploadEquipmentPictureConf(masterWorkOperateCheckInfo.getNeedUploadEquipmentPictureConf())
					.needUploadPurityPicture(masterWorkOperateCheckInfo.getNeedUploadPurityPicture())
					.needUploadPurityPictureConf(masterWorkOperateCheckInfo.getNeedUploadPurityPictureConf())
					.serviceOrderProcess(masterWorkOperateCheckInfo.getServiceOrderProcess())
					.build();
			return ResponseDTO.success(workOperateCheckInfoDRO);
		} catch (Exception e) {
			log.error("getMasterWorkOperateCheckInfo异常:{}", e);
			return ResponseDTO.fail("订单信息不存在");
		}
	}

	/**
	 * 获取工单保修卡二维码
	 *
	 * @param masterWorkDIO
	 */
	@Override
	public ResponseDTO<MasterWorkWarrantyDRO> getWorkWarranty(MasterWorkDIO masterWorkDIO) {
		log.info("获取工单orderId{},workId{}保修卡二维码入参", masterWorkDIO.getOrderId(), masterWorkDIO.getWorkId());
		MasterWorkWarrantyDTO masterWorkWarrantyDTO = zsMasterWorkBService.getWorkWarranty(masterWorkDIO.getOrderId(),
				masterWorkDIO.getWorkId());
		MasterWorkWarrantyDRO masterWorkWarrantyDRO = BeanMapper.map(masterWorkWarrantyDTO, MasterWorkWarrantyDRO.class);
		return ResponseDTO.success(masterWorkWarrantyDRO);
	}

	/**
	 * 获取工单上门二维码
	 *
	 * @param masterWorkDIO
	 */
	@Override
	public ResponseDTO<MasterWorkVisitQrCodeDRO> getWorkVisitQrCode(MasterWorkDIO masterWorkDIO) {
		try {
			MasterWorkVisitQrCodeDTO masterWorkVisitQrCodeDTO = zsMasterWorkBService.getWorkVisitQrCode(masterWorkDIO.getOrderId(), masterWorkDIO.getWorkId());
			MasterWorkVisitQrCodeDRO masterWorkVisitQrCodeDRO = BeanMapper.map(masterWorkVisitQrCodeDTO, MasterWorkVisitQrCodeDRO.class);
			return ResponseDTO.success(masterWorkVisitQrCodeDRO);
		} catch (OmsBaseException e) {
			return ResponseDTO.fail(e.getCode(), e.getMessage());
		}
	}

	/**
	 * 获取最大优惠金额
	 *
	 * @param getMaxDiscountDIO
	 */
	@Override
	public ResponseDTO<Integer> getMaxDiscount(BaseRequestDIO getMaxDiscountDIO) {
		try {
/*			Integer operatorId = OrderConsts.ORDER_OP_TYPE_DISCOUNT_LEVEL_ONE;
			Integer maxDiscountAmount = zsNormalOrderDiscountBService.getMaxDiscountAmount(
					getMaxDiscountDIO.getOrderId(), getMaxDiscountDIO.getWorkId(),
					operatorId, FicoConsts.ORDER_IN_DISCOUNT_CATEG_ARTIFICIAL_MASTER);*/
			OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(getMaxDiscountDIO.getOrderId(), getMaxDiscountDIO.getWorkId());

			List<OrderDiscount> orderDiscounts = Lists.newArrayList();
			if (NumberUtil.isNotNullOrZero(dbOrderWork.getDiscountAmount())) {
				orderDiscounts = orderDiscountService.listByOrderId(getMaxDiscountDIO.getOrderId());
			}
			ReCalcOrderAmountDIO calcOrderAmountDIO = new ReCalcOrderAmountDIO();
			calcOrderAmountDIO.setOrderAmountDIO(BeanMapper.map(dbOrderWork, OrderAmountDIO.class));
			calcOrderAmountDIO.setDiscountConditionParamsDIO(BeanMapper.map(dbOrderWork, DiscountConditionParamsDIO.class));
			calcOrderAmountDIO.setOrderDiscountList(orderDiscounts);
			Integer artificialMaxDiscount = orderDiscountCalcBService.getArtificialMaxDiscount(TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT, calcOrderAmountDIO);

			return ResponseDTO.success(artificialMaxDiscount);
		} catch (OmsBaseException e) {
			return ResponseDTO.fail(e.getCode(), e.getMessage());
		}
	}

	/**
	 * 获取最大定金金额
	 *
	 * @param getMaxDepositAmount
	 */
	@Override
	public ResponseDTO<Integer> getMaxDepositAmount(BaseRequestDIO getMaxDepositAmount) {
		OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(getMaxDepositAmount.getOrderId(), getMaxDepositAmount.getWorkId());
		if (NumberUtil.isNullOrZero(orderWork.getOriginalAmount())) {
			return ResponseDTO.fail("请先选择服务项后再试");
		}

		if (Objects.equals(orderWork.getDepositStatus(), PayConsts.PAY_STATUS_DONE)) {
			return ResponseDTO.fail("定金已经支付");
		}

		int prepayAmount = 0;
		if (Objects.equals(orderWork.getChannelPrepayStatus(), PayConsts.PAY_STATUS_DONE)) {
			prepayAmount =prepayAmount + Optional.ofNullable(orderWork.getChannelPrepayAmount()).orElse(0);
		}
		if (Objects.equals(orderWork.getPrepayStatus(), PayConsts.PAY_STATUS_DONE)) {
			prepayAmount =prepayAmount + Optional.ofNullable(orderWork.getPrepayAmount()).orElse(0);
		}
		int tempAmt = prepayAmount + Optional.ofNullable(orderWork.getDiscountAmount()).orElse(0);
		// 定金范围 = 原价 - 预付金额 - 优惠金额
		return ResponseDTO.success(MathUtil.sub(orderWork.getOriginalAmount().intValue(),tempAmt));
	}

	/**
	 * 是否存在工程师订单（JST聚合塔服务调用）
	 * @param masterId 工程师id
	 * @param leaveStartTime 请假开始时间
	 * @param leaveEndTime 请假结束时间
	 */
	@Override
	public ResponseDTO<Boolean> existEngineerOrder(Integer masterId, Date leaveStartTime, Date leaveEndTime) {

		log.info("工程师请假请求入参masterId[{}],leaveStartTime[{}],leaveEndTime[{}]", masterId, leaveStartTime, leaveEndTime);
		if (NumberUtil.isNullOrZero(masterId)) {
			return ResponseDTO.fail("工程师id不能为空");
		}

		// 1，查询预约时间内的订单数
		OrderWorkQuery query = new OrderWorkQuery();
		query.setMasterId(masterId);// 工程师
		// 预约时间
		if (leaveStartTime != null && leaveEndTime != null) {
			String startTimeStr = DateUtil.toString(leaveStartTime, DateUtil.FORMAT_DEFAULT);
			String endTimeStr = DateUtil.toString(leaveEndTime, DateUtil.FORMAT_DEFAULT);
			query.setDutyTime(startTimeStr + "," + endTimeStr);
		}
		// 已派单 已领单 已上门 --- 进行中
		query.setWorkStatus(Arrays.asList(OrderStatusConsts.WORK_STATUS_DISTRIBUTE, OrderStatusConsts.WORK_STATUS_TAKE, OrderStatusConsts.WORK_STATUS_VISIT));
		query.setWorkResultStatusList(Arrays.asList(OrderStatusConsts.WORK_RESULT_DOING));
		query.setWorkType(Arrays.asList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK));
		Integer count = orderWorkListBService.countOrderWorkByQuery(query);
		if (count > 0) {
			log.info("预约时间内订单数据[{}]", count);
			return ResponseDTO.fail("请假期间有预约中的订单，不支持请假");
		}

		// 2，查询跟单内容有收款未支付的订单数
		query.setDutyTime(null);
		query.setTrackTypeId(Arrays.asList(1034));// 跟单内容为1034（收款未支付）
		Integer count2 = orderWorkListBService.countOrderWorkByQuery(query);
		if (count2 > 0) {
			log.info("收款未支付订单数[{}]", count2);
			return ResponseDTO.fail("有收款未支付订单，请支付后再试");
		}
		return ResponseDTO.success(true);
	}

	/**
	 * 搜索进行中工单
	 * @param orderListDIO 查询条件
	 */
	@Override
	@Deprecated
	public ResponseDTO<WorkListDRO> listPageOrder(OrderListDIO orderListDIO){

		if (log.isDebugEnabled()) {
			log.debug("搜索师傅进行中工单listPageOrder: {}", JSONObject.toJSONString(orderListDIO));
		}
		BoolQueryBuilder boolQueryBuilder = boolQuery();

		// 获取产品二级分类id
		CategProductQuery categProductQuery = new CategProductQuery();
		categProductQuery.setLevel(GlobalConsts.LEVEL_2);
		categProductQuery.setCategName(orderListDIO.getText());
		try {
			ResponseDTO<List<CategProductDRO>> listResponseDTO = categProductListRemoteService.listByQuery(categProductQuery);
			List<CategProductDRO> data = listResponseDTO.getData();
			if (CollectionUtil.isNotNullOrEmpty(data)) {
				//boolQueryBuilder.should(QueryBuilders.termsQuery("categTwoId", categoryDROList.stream().);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		if (orderListDIO.getText().matches("[0-9]+")) {
			boolQueryBuilder.should(QueryBuilders.termQuery("id", orderListDIO.getText()));
		}

		NativeSearchQuery build = new NativeSearchQueryBuilder()
				.withPageable(Pageable.unpaged())
				.withQuery(boolQuery()
						.filter(termQuery("masterId", orderListDIO.getMasterId()))
						.filter(boolQueryBuilder
								.must(QueryBuilders.termsQuery("resultStatus",
										Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING)))
								.must(QueryBuilders.termsQuery("status",
										Lists.newArrayList(OrderStatusConsts.WORK_STATUS_TAKE,OrderStatusConsts.WORK_STATUS_VISIT)))
								.should(QueryBuilders.termQuery("contact.phone", orderEncryptService.encrypt(orderListDIO.getText())))
								.should(QueryBuilders.termQuery("contact.bindPhone",orderListDIO.getText()))
								.should(QueryBuilders.termQuery("codeEnd6",orderListDIO.getText()))
								.should(QueryBuilders.termQuery("contact.contactName",orderListDIO.getText()))
								.should(QueryBuilders.termQuery("contact.userName",orderListDIO.getText()))
								//.should(QueryBuilders.matchQuery("contact.queryFullAddress",orderListDIO.getText()))
						))
				.build();

		List<EsOrderWork> content = orderWorkEsBService.listPageByQuery(build);
		orderEncryptService.batchDecryptEsOrderWork(content,EncryptFieldTypeEnum.USER_FULLADDRESS);// 解密完整地址
		List<WorkListItemDRO> workListItemDROS = Lists.newArrayList();
		content.forEach(esOrderWork->{
			WorkListItemDRO workListItemDRO = new WorkListItemDRO();
			workListItemDRO.setAddress(esOrderWork.getContact().getFullAddress());
			workListItemDRO.setWorkId(esOrderWork.getId());
			workListItemDRO.setOrderId(esOrderWork.getOrderId());
			workListItemDRO.setStatus(esOrderWork.getStatus());
			workListItemDRO.setServItemType(esOrderWork.getServItemType());
			workListItemDRO.setProductInfo(ProductInfoUtil.getProductName(esOrderWork.getProductInfo()));
			workListItemDRO.setDutyTime(esOrderWork.getDutyTime());
			workListItemDRO.setBizType(esOrderWork.getBizType());
			workListItemDROS.add(workListItemDRO);
		});
		WorkListDRO workListDRO = new WorkListDRO();
		workListDRO.setDoingWorkOrders(workListItemDROS);
		return ResponseDTO.success(workListDRO);
	}

	/**
	 * 报价产品记录
	 *
	 * @param orderId
	 */
	@Override
	public ResponseDTO<String> queryProductRecord(Long orderId){

		String str = "";
		try {
			// 查询前先判断后台是否操作过服务项(非用户、师傅)
			OrderOperation orderOperation = orderOperationService.findBykey(orderId);
			List<Integer> typeList = Arrays.asList(GlobalConsts.OPERATE_USER_TYPE_MASTER,GlobalConsts.OPERATE_USER_TYPE_USER);
			if(!typeList.contains(orderOperation.getQuotationType())){
				return ResponseDTO.success(str);
			}
			ResponseDTO<String> quotationSelectInfo = quotationModifyRemoteService.getQuotationSelectInfo(orderId);
			log.info("查询产品报价记录 orderId:{} , response：{} ",orderId,JSONObject.toJSONString(quotationSelectInfo));
			if(quotationSelectInfo.isSuccess()){
				str = quotationSelectInfo.getData();
			}
		}catch (Exception e){
			log.error("查询产品报价记录 orderId:{} , exception：{} ",orderId,e.getMessage());
		}
		return ResponseDTO.success(str);
	}

	/**
	 * 工单附件照片
	 *
	 * @param orderAttachmentDIO
	 */
	@Deprecated
	@Override
	public ResponseDTO<List<OrderAttachmentDRO>> queryOrderAttachment(OrderAttachmentDIO orderAttachmentDIO){
		// 查询渠道图片配置
		OrderAttachmentQuery orderAttachmentQuery = BeanMapper.map(orderAttachmentDIO, OrderAttachmentQuery.class);
		OrderWorkAttachmentVO orderAttachmentVo = orderAttachmentBService.getOrderAttachmentByQuery(orderAttachmentQuery);

		List<OrderWorkAttachmentDetailVO> pictureList = orderAttachmentVo.getPictureList();
		if (CollectionUtils.isEmpty(pictureList)) {
			return ResponseDTO.success(Lists.newArrayList());
		}

		List<OrderAttachmentDRO> orderAttachmentDROS = Lists.newArrayListWithCapacity(pictureList.size());
		pictureList.forEach(item -> {
			OrderAttachmentDRO orderAttachmentDRO = new OrderAttachmentDRO();
			orderAttachmentDRO.setPictureType(item.getType());
			orderAttachmentDRO.setPictureTypeName(item.getTypeName());
			orderAttachmentDRO.setPictureNumber(item.getNumber());
			orderAttachmentDRO.setSrc(item.getSrc());
			orderAttachmentDRO.setPictureSrc(item.getEgSrc());
			orderAttachmentDRO.setRequiredFlag(item.getRequiredFlag());
			orderAttachmentDRO.setAuditFlag(item.getAuditFlag());
			orderAttachmentDROS.add(orderAttachmentDRO);
		});
		return ResponseDTO.success(orderAttachmentDROS);
	}

    @Override
	public ResponseDTO<MasterQuotationDiscountDRO> getQuotationAndDiscountInfo(BaseRequestDIO baseRequestDIO) {
        // 点击『用户已确认报价，开始服务』时判断用户是否“确认报价”，若未完成，则toast提示『用户暂未完成报价，暂时无法服务』
        // 点击『申请优惠』时，判断工单是否已有计价器价格，若没有，则toast提示『用户暂未报价，暂时不能申请优惠』，若有则打开计价器申请优惠页面（页面3）
		OrderWork orderWork = orderWorkService.findOrderWorkByKey(baseRequestDIO.getOrderId(), baseRequestDIO.getWorkId());
        if (Objects.isNull(orderWork)) {
            return ResponseDTO.fail("not find order");
        }
        try {
            MasterQuotationDiscountDTO masterQuotationDTO = zsMasterWorkBService.getQuotationAndDiscountInfo(orderWork);
            MasterQuotationDiscountDRO masterQuotationDRO = BeanMapper.map(masterQuotationDTO, MasterQuotationDiscountDRO.class);
            return ResponseDTO.success(masterQuotationDRO);

        } catch (OmsBaseException e) {
            return ResponseDTO.fail(e.getCode(), e.getMessage());
        }
    }

	/**
	 * 订单数量
	 *
	 * @param engineerId
	 * @param startTime
	 * @param endTime
	 */
	@Override
	public ResponseDTO<OrderCountDRO> queryOrderCount(Integer engineerId, Date startTime, Date endTime) {

		OrderWorkQuery query = new OrderWorkQuery();
		query.setMasterId(engineerId);// 工程师
		query.setPageSize(10000);
		// 预约时间
		if (startTime != null && endTime != null) {
			String startTimeStr = DateUtil.toString(startTime, DateUtil.FORMAT_DEFAULT);
			String endTimeStr = DateUtil.toString(endTime, DateUtil.FORMAT_DEFAULT);
			query.setReceiveTime(startTimeStr + "," + endTimeStr);
		}
		query.setWorkStatus(Arrays.asList(OrderStatusConsts.WORK_STATUS_CHECKOUT,OrderStatusConsts.WORK_STATUS_ACCOUNT));
		OrderCountDRO orderCountDRO = new OrderCountDRO();
		List<EsOrderWork> orderWorkList = orderWorkListBService.listPageOrderWorkByQuery(query);
		orderWorkList = orderWorkList.stream().filter(e -> Objects.isNull(e.getCancelTime())).collect(Collectors.toList());
		if (CollectionUtil.isNotNullOrEmpty(orderWorkList)) {
			Map<Integer, List<EsOrderWork>> collect = orderWorkList.stream().collect(Collectors.groupingBy(EsOrderWork::getResultStatus));
			long accountCount = orderWorkList.stream().filter(e -> e.getStatus().equals(OrderStatusConsts.WORK_STATUS_ACCOUNT)).count();
			long successCount = Optional.ofNullable(collect.get(OrderStatusConsts.WORK_RESULT_SUCCESS)).orElse(new ArrayList<>()).size();
			long failCount = Optional.ofNullable(collect.get(OrderStatusConsts.WORK_RESULT_FAIL)).orElse(new ArrayList<>()).size();
			orderCountDRO = OrderCountDRO.builder().allCount(orderWorkList.size()).accountCount((int) accountCount).successCount((int) successCount).failCount((int) failCount).build();
		}

		return ResponseDTO.success(orderCountDRO);
	}

	/**
	 * 操作结果
	 *
	 * @param orderId
	 * @param operateId
	 */
	@Override
	public ResponseDTO<String> getOperateResult(@NotNull Long orderId, @NotNull Integer operateId) {

		String result = orderWorkProgrammeBService.getOperateInfo(orderId, operateId);

		return ResponseDTO.success(result);
	}

	/**
	 * 批量查询工单详情-投诉列表使用
	 * @param ids
	 * @return
	 */
	@Override
	public ResponseDTO<List<OrderDetailDRO>> getOrderDetailList(List<Long> ids){

		if(CollectionUtil.isNullOrEmpty(ids)){
			return ResponseDTO.success(new ArrayList<>());
		}
		List<OrderDetail> orderDetails = orderDetailService.listOrderDetailByOrderIdList(ids);
		List<OrderWork> orderWorks = orderWorkService.listEsOrderWorkByOrderIdList(ids);
		List<OrderDetailDRO> droList = Lists.newArrayListWithExpectedSize(orderWorks.size());
		Map<Long, OrderDetail> collect = orderDetails.stream().collect(Collectors.toMap(OrderDetail::getDetailId, a -> a, (k1, k2) -> k1));
		orderWorks.forEach(e->{
			OrderDetailDRO dro = BeanMapper.map(collect.get(e.getWorkId()), OrderDetailDRO.class);
			dro.setWorkId(e.getWorkId());
			dro.setDutyTime(e.getDutyTime());
			dro.setProductInfo(ProductInfoUtil.getProductName(dro.getProductInfo()));
			droList.add(dro);
		});
		return ResponseDTO.success(droList);
	};

	/**
	 * 根据工程师最近三个月失败订单的取消缘由id
	 * @param engineerId
	 * @return
	 */
	@Override
	public ResponseDTO<List<Integer>> getCancelReasonIdByEngineerId(Integer engineerId){

		OrderWorkQuery query = new OrderWorkQuery();
		query.setMasterId(engineerId);
		query.setPageSize(10000);
		// 派单时间
		Date endTime = DateUtil.getNow();
		Date startTime = DateUtil.parse(DateUtil.getMonthFirstDay(DateUtil.addMonth(endTime, -2)), DateUtil.FORMAT_DEFAULT);
		String startTimeStr = DateUtil.toString(startTime, DateUtil.FORMAT_DEFAULT);
		String endTimeStr = DateUtil.toString(endTime, DateUtil.FORMAT_DEFAULT);
		query.setDistributeTime(startTimeStr + "," + endTimeStr);
		query.setResultStatusList(Arrays.asList(OrderStatusConsts.WORK_RESULT_FAIL, OrderStatusConsts.WORK_RESULT_DISCARD));

		List<EsOrderWork> orderWorkList = orderWorkListBService.listPageOrderWorkByQuery(query);

		List<Integer> result = Lists.newArrayList();
		if(CollectionUtil.isNotNullOrEmpty(orderWorkList)){
			Set<Integer> ids = Sets.newHashSet();
			orderWorkList.forEach(orderWork->{
				Set<Integer> collect = orderWork.getRemarkDetailList().stream()
						.filter(detail -> Objects.equals(detail.getType(), OrderConsts.ORDER_REMARK_TYPE_CANCEL)).map(EsOrderRemarkDetail::getMapId).collect(Collectors.toSet());
				ids.addAll(collect);
			});
			result = new ArrayList<>(ids);
		}

		return ResponseDTO.success(result);
	}

	@Override
	public ResponseDTO<WorkListDRO> listDoingWork(Integer masterId) {
		log.info("搜索师傅进行中工单masterId: {}", masterId);
		BoolQueryBuilder boolQueryBuilder = boolQuery();
		NativeSearchQuery build = new NativeSearchQueryBuilder()
				.withPageable(Pageable.unpaged())
				.withQuery(boolQuery()
						.filter(termQuery("masterId", masterId))
						.filter(boolQueryBuilder
								.must(QueryBuilders.termsQuery("resultStatus",
										Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING)))
								.must(QueryBuilders.termsQuery("status",
										Lists.newArrayList(OrderStatusConsts.WORK_STATUS_TAKE,OrderStatusConsts.WORK_STATUS_VISIT)))
						))
				.build();

		List<EsOrderWork> content = orderWorkEsBService.listPageByQuery(build);
		orderEncryptService.batchDecryptEsOrderWork(content,EncryptFieldTypeEnum.USER_FULLADDRESS);// 解密完整地址
		List<WorkListItemDRO> workListItemDROS = Lists.newArrayList();
		content.forEach(esOrderWork->{
			WorkListItemDRO workListItemDRO = new WorkListItemDRO();
			workListItemDRO.setAddress(esOrderWork.getContact().getFullAddress());
			workListItemDRO.setWorkId(esOrderWork.getId());
			workListItemDRO.setOrderId(esOrderWork.getOrderId());
			workListItemDRO.setStatus(esOrderWork.getStatus());
			workListItemDRO.setServItemType(esOrderWork.getServItemType());
			workListItemDRO.setProductInfo(ProductInfoUtil.getProductName(esOrderWork.getProductInfo()));
			workListItemDRO.setDutyTime(esOrderWork.getDutyTime());
			workListItemDRO.setTakeTime(esOrderWork.getTakeTime());
			workListItemDRO.setBizType(esOrderWork.getBizType());
			workListItemDRO.setReceiveTime(esOrderWork.getInputTime());
			workListItemDRO.setServProductGroupId(esOrderWork.getServProductGroupId());
			workListItemDRO.setServProductGroupName(esOrderWork.getServProductGroupName());
			workListItemDROS.add(workListItemDRO);
		});
		WorkListDRO workListDRO = new WorkListDRO();
		workListDRO.setDoingWorkOrders(workListItemDROS);
		return ResponseDTO.success(workListDRO);
	}

	@Override
	public ResponseDTO<List<Long>> getOrderIdListByEngineerIdAndDutyTime(@NotNull(message = "工程师ID不能为空") Integer engineerId, @NotNull(message = "预约开始时间不能为空") Date startTime, @NotNull(message = "预约结束时间不能为空") Date endTime) {
		OrderWorkQuery query = new OrderWorkQuery();
		query.setMasterId(engineerId);
		query.setPageSize(10000);
		String startTimeStr = DateUtil.toString(startTime, DateUtil.FORMAT_DEFAULT);
		String endTimeStr = DateUtil.toString(endTime, DateUtil.FORMAT_DEFAULT);
		query.setDutyTime(startTimeStr + "," + endTimeStr);
		query.setWorkResultStatus(OrderStatusConsts.WORK_RESULT_DOING);

		List<EsOrderWork> orderWorkList = orderWorkListBService.listPageOrderWorkByQuery(query);

		List<Long> result = Lists.newArrayList();
		if(CollectionUtil.isNotNullOrEmpty(orderWorkList)){
			result = orderWorkList.stream().map(EsOrderWork::getId).collect(Collectors.toList());
		}

		return ResponseDTO.success(result);
	}
}
